/***************************************************************************
                          Zoomable.cpp  -  description
                             -------------------
    begin                : October 29 2009
    copyright            : Copyright 2009, ACKERMANN Thibaut
    email                : tackerma@edu.univ-fcomte.fr
    website              : http://code.google.com/p/nover-project/
    license              : GNU GPL v3
 ***************************************************************************/
/* *************************************************************************
 *  This file is part of NOver-Project.
 *  
 *  NOver-Project is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  NOver-Project is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with NOver-Project.  If not, see <http://www.gnu.org/licenses/>.
 * *************************************************************************/


#include "Zoomable.hpp"


Zoomable::Zoomable(IGUIElement* parent, s32 id, core::rect<s32> rectangle)
				  : gui::IGUIElement(gui::EGUIET_ELEMENT, StateMgr::Instance()->getGuiEnv(), parent, id, rectangle),
				  	Texture(0),
				    zoomlevel(ZOOM_LEVEL_0_ALL),
				    AbsoluteRenderRect(rectangle),
				    TextureRenderRect(core::rect<s32>(0, 0, 0, 0))
{
}


Zoomable::~Zoomable()
{
	if(Texture)
		Texture->drop();
}


void Zoomable::draw()
{
	if (!IsVisible)
		return;
	video::IVideoDriver* driver = Environment->getVideoDriver();	if (Texture)	{
		// doit absolument être appelée avant le rendu, car la fonction agit sur AbsoluteRenderRect
		// core::position2d<s32> rightdownpos = calculateRightDownViewCorner();
		
		driver->draw2DImage(Texture, AbsoluteRenderRect, TextureRenderRect);	}	else	{
		// TODO : couleur à modifier.
		driver->draw2DRectangle(video::SColor(127, 255, 0, 0), AbsoluteRect, 0);	}
	
	// pour les eventuels enfants.	IGUIElement::draw();
}


void Zoomable::calculateRendersRect()
{
	// fonction de calcul de la zone a rendre de la texture.

	switch(zoomlevel)
	{
	
	case ZOOM_LEVEL_0_ALL:
	{
		float Tx = Texture->getOriginalSize().Width / static_cast<float>(AbsoluteRect.getWidth());
		float Ty = Texture->getOriginalSize().Height / static_cast<float>(AbsoluteRect.getHeight());
		
		
		AbsoluteRenderRect = AbsoluteRect;
		
		if(Tx > Ty)
		{
			AbsoluteRenderRect.LowerRightCorner.Y = (AbsoluteRect.getWidth()*Texture->getOriginalSize().Height)/static_cast<float>(Texture->getOriginalSize().Width);
			
		} else if(Tx < Ty) {
			
			AbsoluteRenderRect.LowerRightCorner.X = (AbsoluteRect.getHeight()*Texture->getOriginalSize().Width)/static_cast<float>(Texture->getOriginalSize().Height);
		}
		
		// si Tx == Ty
		// equals.
		// on ne touche pas à l'absolute rect
		
		TextureRenderRect.LowerRightCorner = core::position2d<s32>(Texture->getOriginalSize().Width, 
											Texture->getOriginalSize().Height) + 
											TextureRenderRect.UpperLeftCorner;
		
		return;
	}
	case ZOOM_LEVEL_1_OPTIMAL:
	{
		AbsoluteRenderRect = AbsoluteRect;
		
		// TODO : a checker ! fonctionnement incorrect
		
		if(AbsoluteRect.getWidth() > AbsoluteRect.getHeight())
		{
			float test = AbsoluteRect.getHeight() / static_cast<float>(AbsoluteRect.getWidth());
		
			TextureRenderRect.LowerRightCorner = core::position2d<s32>(Texture->getOriginalSize().Width, 
											 Texture->getOriginalSize().Height*test) +
											 TextureRenderRect.UpperLeftCorner;
		
		} else {
		
			float test = AbsoluteRect.getWidth() / static_cast<float>(AbsoluteRect.getHeight());
		
			TextureRenderRect.LowerRightCorner = core::position2d<s32>(Texture->getOriginalSize().Width*test, 
											 Texture->getOriginalSize().Height) +
											 TextureRenderRect.UpperLeftCorner;
		
		}
		
		return;
	}
	case ZOOM_LEVEL_2_ZOOMED:
	{
		AbsoluteRenderRect = AbsoluteRect;
		
		TextureRenderRect.LowerRightCorner = core::position2d<s32>(
											 Texture->getOriginalSize().Width*0.5f, 
											 Texture->getOriginalSize().Height*0.5f) + 
											 TextureRenderRect.UpperLeftCorner;
		
		return;
	}
	
	}// end of switch
}



// attention : (x1,y1) et (x2,y2) sont des points du rectangle AbsoluteRect
void Zoomable::Drag(int x1, int y1, int x2, int y2)
{
	// TODO : eventuelmemnt utiliser ScreenToTexture()
	// agit sur le TextureRenderRect
	int xMin = TextureRenderRect.UpperLeftCorner.X;
	int xMax = TextureRenderRect.LowerRightCorner.X;
	int yMin = TextureRenderRect.UpperLeftCorner.Y;
	int yMax = TextureRenderRect.LowerRightCorner.Y;
	
	x1 = ((x1*(xMax - xMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.X)) + xMin;
	y1 = ((y1*(yMax - yMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.Y)) + yMin;
	
	x2 = ((x2*(xMax - xMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.X)) + xMin;
	y2 = ((y2*(yMax - yMin))/static_cast<float>(AbsoluteRenderRect.LowerRightCorner.Y)) + yMin;
	
	core::position2d<int> sub = core::position2d<int>(x1, y1) - core::position2d<int>(x2, y2);
	
	TextureRenderRect.LowerRightCorner += sub;
	TextureRenderRect.UpperLeftCorner += sub;
	
	
	// on check qu'on dépasse pas
	if(TextureRenderRect.UpperLeftCorner.X < 0)
	{
		TextureRenderRect.LowerRightCorner.X -= TextureRenderRect.UpperLeftCorner.X;
		TextureRenderRect.UpperLeftCorner.X = 0;
	}
	
	if(TextureRenderRect.UpperLeftCorner.Y < 0)
	{
		TextureRenderRect.LowerRightCorner.Y -= TextureRenderRect.UpperLeftCorner.Y;
		TextureRenderRect.UpperLeftCorner.Y = 0;
	}
	
	if(TextureRenderRect.LowerRightCorner.X > Texture->getOriginalSize().Width)
	{
		TextureRenderRect.UpperLeftCorner.X -= TextureRenderRect.LowerRightCorner.X - Texture->getOriginalSize().Width;
		TextureRenderRect.LowerRightCorner.X = Texture->getOriginalSize().Width;
	}
	
	if(TextureRenderRect.LowerRightCorner.Y > Texture->getOriginalSize().Height)
	{
		TextureRenderRect.UpperLeftCorner.Y -= TextureRenderRect.LowerRightCorner.Y - Texture->getOriginalSize().Height;
		TextureRenderRect.LowerRightCorner.Y = Texture->getOriginalSize().Height;
	}
}


